package com.bjpowernode.shop.listener;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bjpowernode.shop.Feign.ProdServiceFeign;
import com.bjpowernode.shop.base.BaseOrder;
import com.bjpowernode.shop.constants.QueueConstants;
import com.bjpowernode.shop.domain.CountVo;
import com.bjpowernode.shop.domain.OrderTbl;
import com.bjpowernode.shop.domain.ProdCount;
import com.bjpowernode.shop.domain.SkuCount;
import com.rabbitmq.client.Channel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.util.Date;
import java.util.List;

@Configuration
public class ReceiveQueueListener extends BaseOrder {

    @RabbitListener(queues = {QueueConstants.ORDER_MS_QUEUE})
    public void receiveMsgFromOrderMsgQueue(Message message, Channel channel) {
        System.out.println("new Date() = " + new Date());
        System.out.println("尝试消费ms消息");
        // 将消息转换为对象
        String json = new String(message.getBody());
        CountVo countVo = JSON.parseObject(json, CountVo.class);

        // 找到对应订单
        String orderNumber = countVo.getOrderNumber();
        OrderTbl orderTbl = orderTblService.getOne(new LambdaQueryWrapper<OrderTbl>().eq(
                StringUtils.isNotEmpty(orderNumber), OrderTbl::getOrderNumber, orderNumber
        ));

        // 判断是否支付
        if (orderTbl.getIsPayed().equals(1)) {
            // 已支付则消费消息
            try {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                System.out.println("ms消息消费成功");
            } catch (IOException e) {
                e.printStackTrace();
                try {
                    // long deliveryTag, boolean multiple, boolean requeue
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
                    System.out.println("ms消息消费失败且重回队列");
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        }

        // 未支付且消息阻塞Unacked时将消息重回队列
        try {
            // long deliveryTag, boolean multiple, boolean requeue
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            System.out.println("ms消息重回队列");
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
        // 未支付且超时则转发到死信队列中
    }

    @Autowired
    private ProdServiceFeign prodServiceFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    @RabbitListener(queues = {QueueConstants.ORDER_DEAD_QUEUE})
    public void receiveMsgFromOrderDeadQueue(Message message, Channel channel) {
        System.out.println("new Date() = " + new Date());
        System.out.println("尝试消费dead消息");
        String json = new String(message.getBody());
        CountVo countVo = JSON.parseObject(json, CountVo.class);

        // 补回mysql库存
        List<ProdCount> prodCountList = countVo.getProdCountList();
        prodCountList.forEach(
                prodCount -> prodCount.setCount(prodCount.getCount() * -1)
        );

        List<SkuCount> skuCountList = countVo.getSkuCountList();
        skuCountList.forEach(
                skuCount -> skuCount.setCount(skuCount.getCount() * -1)
        );

        Boolean flag = prodServiceFeign.deductDbStock(countVo);
        if (!flag)
            throw new RuntimeException("mysql库存补回失败");
        System.out.println("mysql库存补回成功");

        // 补回es库存
        rabbitTemplate.convertAndSend(
                QueueConstants.ES_CHANGE_QUEUE,
                JSON.toJSONString(prodCountList)
        );
        System.out.println("es库存补回成功");

        // 补回完成后消费消息
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            System.out.println("dead消息消费成功");
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
